package cn.lg.soar.common.util;

import javax.servlet.http.HttpServletRequest;
import java.net.*;
import java.util.Enumeration;

/**
 * IP工具
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public interface IpUtil {

    String CLIENT_IP = "soar-client-ip";

    /**
     * 获取本机ip
     * @return
     */
    static String getLocalIp(){
        if (StaticCache.LOCAL_IP == null) {
            synchronized (IpUtil.class){
                try {
                    Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces();
                    while (allNetInterfaces.hasMoreElements()) {
                        NetworkInterface netInterface = allNetInterfaces.nextElement();
                        if (netInterface.isLoopback() || netInterface.isVirtual() || !netInterface.isUp()) {
                            continue;
                        }
                        Enumeration<InetAddress> addresses = netInterface.getInetAddresses();
                        while (addresses.hasMoreElements()) {
                            InetAddress ip = addresses.nextElement();
                            if (ip instanceof Inet4Address) {
                                StaticCache.LOCAL_IP = ip.getHostAddress();
                            }
                        }
                    }
                } catch (SocketException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return StaticCache.LOCAL_IP;
    }

    /**
     * 获取本机ipv6
     * @return
     */
    static String getLocalIp6(){
        if (StaticCache.LOCAL_IP6 == null) {
            synchronized (IpUtil.class) {
                try {
                    Enumeration<NetworkInterface> allNetInterfaces = NetworkInterface.getNetworkInterfaces();
                    while (allNetInterfaces.hasMoreElements()) {
                        NetworkInterface netInterface = allNetInterfaces.nextElement();
                        if (netInterface.isLoopback() || netInterface.isVirtual() || !netInterface.isUp()) {
                            continue;
                        }
                        Enumeration<InetAddress> addresses = netInterface.getInetAddresses();
                        while (addresses.hasMoreElements()) {
                            InetAddress ip = addresses.nextElement();
                            if (ip instanceof Inet6Address) {
                                StaticCache.LOCAL_IP6 = ip.getHostAddress().split("%")[0];
                            }
                        }
                    }
                } catch (SocketException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return StaticCache.LOCAL_IP6;
    }

    /**
     * 获取真实客户端ip地址（并不保证突破任意代理服务器）
     * @param request
     * @return
     */
    static String getRemoteIp(HttpServletRequest request){
        String ip = request.getHeader(CLIENT_IP);
        if(ip != null && ip.length() != 0) {
            return fmtIp(ip);
        }
        ip = request.getHeader("x-forwarded-for");
        if(ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            ip = ip.split(",")[0];
            return fmtIp(ip);
        }
        // nginx 代理服务器
        ip = request.getHeader("X-Real-IP");
        if(ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            return fmtIp(ip);
        }
        // apache http 做代理
        ip = request.getHeader("Proxy-Client-IP");
        if(ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            return fmtIp(ip);
        }
        // weblogic 插件
        ip = request.getHeader("WL-Proxy-Client-IP");
        if(ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            return fmtIp(ip);
        }
        // 有些代理服务器
        ip = request.getHeader("HTTP_CLIENT_IP");
        if(ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            return fmtIp(ip);
        }
        return fmtIp(request.getRemoteAddr());
    }

    /**
     * 根据 request 获取真实客户端int类型ip地址
     * @param request
     * @return
     */
    static int getRemoteIpInt(HttpServletRequest request){
        String[] strings = getRemoteIp(request).split("\\.");
        int ip = Integer.parseInt(strings[0]) << 24 |
                Integer.parseInt(strings[1]) << 16 |
                Integer.parseInt(strings[2]) << 8 |
                Integer.parseInt(strings[3]);
        return ip;
    }

    /**
     * 将字符串类型ip转为int类型ip
     */
    static int ip4vToInt(String ip4v){
        ip4v = fmtIp(ip4v);
        String[] strings = ip4v.split("\\.");
        int ip = Integer.parseInt(strings[0]) << 24 |
                Integer.parseInt(strings[1]) << 16 |
                Integer.parseInt(strings[2]) << 8 |
                Integer.parseInt(strings[3]);
        return ip;
    }

    /**
     * 将int类型ip转为字符串类型ip
     */
    static String intIpToIpv4(int intIp){
        String[] strings = {
                String.valueOf(intIp >> 24 & 0xFF),
                String.valueOf(intIp >> 16 & 0xFF),
                String.valueOf(intIp >> 8 & 0xFF),
                String.valueOf(intIp & 0xFF)
        };

        return String.join(".", strings);
    }

    static String fmtIp(String ip){
        ip = ip.split(",")[0];
        if("localhost".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)){
            return "127.0.0.1";
        }
        return ip;
    }

    class StaticCache{

        private static String LOCAL_IP;

        private static String LOCAL_IP6;

    }
}
